package nancal.mp.entity.dev

import nancal.mp.entity.base.TestBase
import nbcp.base.db.CodeValue
import nbcp.base.extend.Slice
import nbcp.base.extend.resolvePath
import nbcp.base.utils.FileUtil
import nbcp.myoql.code.generator.db.es.EsMappingGenerator
import nbcp.myoql.code.generator.db.es.EsrGenerator4Kotlin
import nbcp.myoql.code.generator.db.mongo.MorGenerator4Kotlin
import nbcp.myoql.code.generator.db.mysql.DbrGenerator4Kotlin
import nbcp.myoql.code.generator.tool.Enum4JsGenerator
import org.junit.jupiter.api.Test
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
import java.nio.charset.StandardCharsets


class tool : TestBase() {


    @Test
    fun GenEnum_Generator() {
        Enum4JsGenerator.generateEnum("nancal.mp.db.mongo.")
    }

    var reports = mutableListOf<CodeValue>();

    /**
     * 阿里云导出的 csv， null 变成了无内容： ,, ， 该方法把 ,, -->  ,\N,
     * 并拆分 csv文件，每个文件保留第1行的列标题。每个文件十万行, 本地执行大概5秒完成
     */
    @Test
    fun proc_csv_n() {
        var path = File("/home/yuxh/Downloads")
        File(path.path + "/target").apply {
            if (this.exists()) {
                this.deleteRecursively();
            }

            this.mkdirs();
        }

        path.listFiles { dir, name -> name.endsWith(".csv") }.forEach forRoot@{ file ->

            println("正在处理: ${file.name}")

            var procedTitle = false;
            var title = "";
            var procLines = -1;


            file.bufferedReader(StandardCharsets.UTF_8).useLines { lines ->
                lines.forEach { line ->
                    if (!procedTitle) {
                        procedTitle = true;
                        title = line.trim();

                        if (title.get(0) == '\uFEFF') {
                            title = title.Slice(1);
                        }

                        return@forEach;
                    }

                    if (line.isEmpty()) {
                        return@forEach;
                    }

                    procLines++;

                    if (procLines % 10_0000 == 0) {
                        newTarget(file, procLines / 10_0000, title);
                    }

                    writeTarget(transformCsvN(line));
                }

                endCurrentTarget();
            }
        }

        println("处理完成!")


        var txt = reports.groupBy { it.code }.map {
            var tableName = it.key;
            var items = it.value.map { it.value }
            return@map "# ${tableName}: 共${items.size}个\n\ntruncate table ${tableName};${items.joinToString("\n")}"
        }.joinToString("\n")

        println(txt);

        File(path.path + "/report.txt").writeText(txt)
    }


    /**
     * risk_blacklist_library_0.csv
     */
    fun newTarget(file: File, index: Int, title: String) {
        currentWriter?.writer?.flush()
        currentWriter?.writer?.close()


        var tableName = file.nameWithoutExtension.split("_").Slice(0, -1).joinToString("_")
        var fileName = "n---${tableName}-${index}.csv"

        var tf = File(file.parent + "/target/" + fileName)
        if (tf.exists()) {
            tf.delete();
        }
        tf.createNewFile()



        reports.add(
            CodeValue(
                tableName,
                """
# 导入 ${tableName} - ${index}
LOAD DATA INFILE '/var/lib/mysql-files/${fileName}'
INTO TABLE ${tableName}
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS  
( ${title.split(",").map { "`${it.trim()}`" }.joinToString(", ")} ) ;
"""
            )
        )
        currentWriter = FileWriter(file.path, index, tf.bufferedWriter(StandardCharsets.UTF_8))

        currentWriter!!.writer.write(title)
        currentWriter!!.writer.newLine();
    }

    fun endCurrentTarget() {
        currentWriter?.writer?.flush()
        currentWriter?.writer?.close()

        currentWriter = null
    }

    private fun writeTarget(msg: String) {
        currentWriter!!.writer.write(msg)
        currentWriter!!.writer.newLine();
    }


    fun transformCsvN(line: String): String {
        val fields = mutableListOf<String>()
        var current = StringBuilder()
        var inQuotes = false    // 是否处于双引号包裹的字符串内
        var i = 0
        val length = line.length


        while (i < length) {
            val c = line[i]

            if( c == '"'){
                // 切换引号状态（进入或退出字符串）
                inQuotes = !inQuotes
                current.append(c) // 保留引号
                i++
            }
            else if (c == '\\' && i + 1 < length){
                // 处理反斜线转义（如\"、\\等）
                current.append(c)
                current.append(line[i + 1]) // 保留转义后的字符
                i += 2 // 跳过转义字符
            }
            else if(c =='\\'){
                //最后是一个 \, 属于异常
                println("异常: 最后是一个\\")
                current.append(c)
                i++;
            }
            else if( c == ',' && !inQuotes ) {
                // 非引号内的逗号才是字段分隔符
                fields.add(current.toString())
                current.clear()
                i++
            }
            else{
                // 普通字符直接添加
                current.append(c)
                i++
            }
        }
        // ,a,  是3部分, 添加最后一个逗号后面的内容
        fields.add(current.toString())

        //println("每一项: " + fields.map{"(${it})"}.joinToString(" "))

        // 替换空项（非引号包裹的空字符串）为\N
        val transformed = fields.map { field ->
            if (field.isEmpty()) "\\N" else field
        }

        return transformed.joinToString(",")
    }


    var currentWriter: FileWriter? = null

    data class FileWriter(var fileName: String = "", var index: Int = 0, var writer: BufferedWriter)
}
